//
//  HealthKitManage.m
//  Walk
//
//  Created by 黄世淞 on 2018/6/2.
//  Copyright © 2018年 黄世淞. All rights reserved.
//

#import "HealthKitManager.h"

@implementation HealthKitManager
+(id)shareInstance
{
    static id manager ;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[[self class] alloc] init];
    });
    return manager;
}
/**
 检查是否支持获取健康数据
 */
- (void)authorizeHealthKit:(void(^)(BOOL success, NSError * error))compltion{
    if (HKVersion >= 8.0) {
        if (![HKHealthStore isHealthDataAvailable]) {
            NSError * error = [NSError errorWithDomain:@"com.raywenderlich.tutorials.healthkit" code:2 userInfo:[NSDictionary dictionaryWithObject:@"HealthKit is not available in the Device" forKey:NSLocalizedDescriptionKey]];
            if (compltion != nil) {
                compltion(NO,error);
            }
            return;
        }else{
            //获取到需要读取的数据集
            NSSet * writeDataTypes = [self dateTypesToWrite];
            NSSet * readDataTypes = [self dataTypeRead];
            [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError * _Nullable error) {
                if (compltion != nil) {
                    compltion(success,error);
                }
            }];
        }
    }else{
        NSDictionary * userInfo = [NSDictionary dictionaryWithObject:@"iOS 系统低于8.0" forKey:NSLocalizedDescriptionKey];
        NSError * aError = [NSError errorWithDomain:CustomHealthErrorDomain code:0 userInfo:userInfo];
        compltion(NO,aError);
    }
}

/**
 写入权限
 */
- (NSSet *)dateTypesToWrite{
    HKQuantityType * heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
    HKQuantityType * weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
    HKQuantityType * temperatureType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
    HKQuantityType * activeEnergyType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
    return [NSSet setWithObjects:heightType,weightType,temperatureType,activeEnergyType, nil];
}

/**
 读取权限
 */
- (NSSet *)dataTypeRead{
        HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
        HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
        HKQuantityType *temperatureType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
        HKCharacteristicType *birthdayType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];
        HKCharacteristicType *sexType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
        HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
        HKQuantityType *distance = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
        HKQuantityType *activeEnergyType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
    
        return [NSSet setWithObjects:heightType, temperatureType,birthdayType,sexType,weightType,stepCountType, distance, activeEnergyType,nil];
}
#pragma mark ---  时间段
/**
 获取两个日期的时间段
 
 @param startDate 开始日期
 @param endDate 结束日期
 @return 时间段
 */
+ (NSPredicate *)predicateStartDate:(NSDate *)startDate endDate:(NSDate *)endDate{
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
    return predicate;
}

/**
 当天时间段
 
 @return 时间段
 */
+ (NSPredicate *)predicateForToday{
    NSDate * today = [NSDate date];
    return [HealthKitManager predicateForDate:today];
    
}

/**
 某一天的时间段（0：00-24：00）
 
 @param date date
 @return 时间段
 */
+ (NSPredicate *)predicateForDate:(NSDate *)date{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:date];
    [components setHour:0];
    [components setMinute:0];
    [components setSecond: 0];
    NSDate *startDate = [calendar dateFromComponents:components];
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
    return [HealthKitManager predicateStartDate:startDate endDate:endDate];
}
#pragma mark ---  获取步数
/**
 根据时间段获取步数

 @param predicate 时间段
 */
- (void)getStepCountWithPredicate:(NSPredicate *)predicate
                       completion:(void(^)(NSInteger stepCount,NSError * error))completion{
    HKQuantityType * stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    NSSortDescriptor * timeSortDescriptor = [[NSSortDescriptor alloc]initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
    HKSampleQuery * query = [[HKSampleQuery alloc]initWithSampleType:stepType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
        if (error) {
            completion(0,error);
        }else{
            NSInteger totalSteps = 0;
            for (HKQuantitySample * quantitySample in results) {
                HKQuantity * quantity = quantitySample.quantity;
                HKUnit * stepUnit = [HKUnit countUnit];
                double stepCount = [quantity doubleValueForUnit:stepUnit];
                totalSteps += stepCount;
            }
            completion(totalSteps,error);
        }
    }];
    [self.healthStore executeQuery:query];
}

/**
 获取今日的步数
 */
- (void)getStepCountForToday:(void(^)(NSInteger stepCount,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateForToday];
    [self getStepCountWithPredicate:predicate completion:^(NSInteger stepCount, NSError *error) {
        NSLog(@"\n今天行走的步数：%ld\n",(long)stepCount);
        completion(stepCount,error);
    }];
}

/**
 获取指定日期的步数

 @param date 指定日期
 */
- (void)getStepCountForDate:(NSDate *)date
                 completion:(void(^)(NSInteger stepCount,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateForDate:date];
    [self getStepCountWithPredicate:predicate completion:^(NSInteger stepCount, NSError *error) {
        NSLog(@"\n%@---行走的步数：%ld\n",date,(long)stepCount);
        completion(stepCount,error);
    }];
}

/**
 获取两个日期间的步数

 @param startDate 开始日期
 @param endDate 结束日期
 */
- (void)getStepCountForStartDate:(NSDate *)startDate
                         endDate:(NSDate *)endDate
                      completion:(void(^)(NSInteger stepCount,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateStartDate:startDate endDate:endDate];
    [self getStepCountWithPredicate:predicate completion:^(NSInteger stepCount, NSError *error) {
        NSLog(@"\n%@ 至 %@  ---行走的步数：%ld\n",startDate,endDate,(long)stepCount);
        completion(stepCount,error);
    }];
}
#pragma mark --- 获取距离（步行 + 跑步）
/**
 根据时间段获取距离
 
 @param predicate 时间段
 */
- (void)getDistanceWithPredicate:(NSPredicate *)predicate
                      completion:(void(^)(double distance,NSError * error))completion{
    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:distanceType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
        if(error)
        {
            completion(0,error);
        }
        else
        {
            double totalDistances = 0;
            for(HKQuantitySample * quantitySample in results)
            {
                HKQuantity * quantity = quantitySample.quantity;
                HKUnit * distanceUnit = [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixKilo];
                double distance = [quantity doubleValueForUnit:distanceUnit];
                totalDistances += distance;
            }
            completion(totalDistances,error);
        }
    }];
    [self.healthStore executeQuery:query];
}
/**
 获取今日的距离
 */
- (void)getDistanceForToday:(void(^)(double distance,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateForToday];
    [self getDistanceWithPredicate:predicate completion:^(double distance, NSError *error) {
        completion(distance,error);
        NSLog(@"\n今天路程%.2f\n",distance);
    }];
}
/**
 获取指定日期的距离
 
 @param date 指定日期
 */
- (void)getDistanceForDate:(NSDate *)date
                completion:(void(^)(double distance,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateForDate:date];
    [self getDistanceWithPredicate:predicate completion:^(double distance, NSError *error) {
        completion(distance,error);
        NSLog(@"\n%@ --- 路程%.2f\n",date,distance);
    }];
}
/**
 获取两个日期间的距离
 
 @param startDate 开始日期
 @param endDate 结束日期
 */
- (void)getDistanceForStartDate:(NSDate *)startDate
                        endDate:(NSDate *)endDate
                     completion:(void(^)(double distance,NSError * error))completion{
    NSPredicate * predicate = [HealthKitManager predicateStartDate:startDate endDate:endDate];
    [self getDistanceWithPredicate:predicate completion:^(double distance, NSError *error) {
        completion(distance,error);
        NSLog(@"\n%@ 至 %@  --- 路程%.2f\n",startDate,endDate,distance);
    }];
}
#pragma mark --- 卡路里
/**
 根据步数 换上卡路里
 
 @param stepCount 步数
 @return 卡路里
 */
- (double)calorieForStepCount:(NSInteger)stepCount{
    return stepCount * 0.04;
}
- (HKHealthStore *)healthStore{
    if (!_healthStore) {
        _healthStore = [[HKHealthStore alloc]init];
    }
    return _healthStore;
}

@end
